<?php

namespace App\Kuafu\Order\Controller\Applet;

use App\Kuafu\Base\Controller\BaseController;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\CouponExt\Channel\DouYin\DouyinCouponBase;
use App\Kuafu\CouponPackage\Service\CouponPackageService;
use App\Kuafu\Customer\Enum\PlatformCodeEnum;
use App\Kuafu\Customer\Model\CustomerPlatformModel;
use App\Kuafu\Customer\Service\CustomerPlatformService;
use App\Kuafu\Dashboard\Service\PosOnlineService;
use App\Kuafu\Order\Enum\CodeEnum;
use App\Kuafu\Order\Enum\OrderCacheEnum;
use App\Kuafu\Order\Enum\OrderCodeEnum;
use App\Kuafu\Order\Enum\OrderInfoEnum;
use App\Kuafu\Order\Exceptions\OrderException;
use App\Kuafu\Order\Jobs\PayOrderJob;
use App\Kuafu\Order\Service\ConsumerOrderService;
use App\Kuafu\Order\Service\OrderDyService;
use App\Kuafu\Order\Service\OrderHandleService;
use App\Kuafu\Order\Service\OrderPay;
use App\Kuafu\Order\Service\OrderPayService;
use App\Kuafu\Order\Service\OrderService;
use App\Kuafu\Order\Service\OrderUserService;
use App\Kuafu\Pay\Exceptions\PayException;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\User\Exceptions\UserException;
use App\Kuafu\Wechat\Exceptions\WechatException;
use App\Kuafu\Wechat\Service\WechatService;
use App\Support\AppletEncrypt;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class DyOrderCallbackController extends BaseController
{
    public function callback(Request $request)
    {
        $requestAll = $request->all();
        $msgData    = $requestAll['msg'];
    }

    /**
     * 预下单
     * @param Request $request
     * @return JsonResponse
     */
    public function preOrder(Request $request): JsonResponse
    {
        try {
            $requestAll = $request->all();
            $msgData    = $requestAll['msg'];

            $data        = json_decode($msgData, 1);
            $cpExtra     = $data['cp_extra'];
            $cpExtraData = json_decode($cpExtra, 1);
            $couponInfo  = $cpExtraData['couponInfo'];

            $skuList = $data['sku_list'];

            // 校验下单请求

            $productId  = $cpExtraData['couponInfo']['sku_info']['third_sku_id'];
            $productExp = explode('-', $productId);
            $productId  = $productExp[0];
            $productNum = $productExp[1] ?? 1;

            // 商品合规性
            if (empty($productId)) {
                return $this->fail(0, '不存在的关联商品');
            }

            $order_valid_time = [];
            $quantity         = 1;
            foreach ($skuList as $sku) {
                $quantity           = $sku['quantity'];
                $order_valid_time[] = [
                    'goods_id'         => $sku['sku_id'],
                    'valid_start_time' => $cpExtraData['couponInfo']['start_time'] * 1000,
                    'valid_end_time'   => $cpExtraData['couponInfo']['expire_time'] * 1000,
                ];
            }

            // 营业状态, 收银机状态
            ShopService::checkShopOrderStatus($cpExtraData['shopId']);

            // 收银机在线状态
            if (!isTest() && !PosOnlineService::checkPosOnline($cpExtraData['shopId'])) {
                throw new OrderException(OrderCodeEnum::ERR_POS_OFFLINE_STATUS);
            }

            // TODO 时间合规性
            $dyOrder = new OrderDyService(1, $cpExtraData['shopId']);

            $buildCoupon = DouyinCouponBase::DY_KF_SELF_BUILD_PREFIX . $couponInfo['certificate_id'] . '-' . $couponInfo['sku_info']['account_id'] . '-' . $couponInfo['sku_info']['sku_id'];

            Redis::SETEX('dy_build_code:' . $buildCoupon, 3600, json_encode($couponInfo));

            $postData = [
                'unionId'          => $data['union_id'],
                'detail'           => [
                    [
                        'productId' => $productId,
                        'num'       => $quantity * $productNum,
                    ]
                ],
                'thirdOrderId'     => $data['order_id'],
                'thirdOrderSource' => CodeEnum::THIRD_ORDER_SOURCE_DY,
                'extCoupon'        => [
                    [
                        "code"    => $buildCoupon,
                        "codeUrl" => $buildCoupon,
                        "num"     => $quantity,
                        "type"    => OrderInfoEnum::POS_ORDER_PAYMENT_COUPON_DOUYIN,
                    ]
                ],
                'remark'           => $cpExtraData['remark'] ?? ''
            ];

            $orderHandle = $dyOrder->genOrder($postData);

            $returnData = [
                'out_order_no'       => $orderHandle->getOrderId(),
                'pay_expire_seconds' => 300, //支付超时时间，单位秒，例如300表示300秒后过期；不传或传0会使用默认值300
                'order_entry_schema' => [
                    'path'   => 'pages/order/detail', // 小程序页面路径
                    'params' => json_encode([
                        'id'     => $orderHandle->getOrderId(),
                        'shopId' => $cpExtraData['shopId']
                    ])
                ],
                'order_valid_time'   => $order_valid_time
            ];

            if (empty($returnData['out_order_no'])) {
                return $this->fail(999, '订单创建失败,请去门店重新下单');
            }

            // 更新用户信息
            $orderPay = new OrderPay(1, $cpExtraData['shopId'], $orderHandle->getOrderId());
            $orderPay->setUserInfo([
                'userId'     => $orderHandle->getUserId(),
                'openId'     => $data['open_id'],
                'platformId' => PlatformCodeEnum::PLATFORM_APPLET_DOUYIN,
                'unionid'    => $data['union_id'],
            ]);
            $orderPay->updateOrderPayInfo();

            return $this->success($returnData);
        } catch (\Exception $exception) {
            Log::channel('order')->error('Douyin_Order_tools_error', [
                'exception' => $exception
            ]);
            return $this->fail($exception->getCode(), $exception->getMessage());
        }
    }

    public function demo(): JsonResponse
    {
        return $this->success([]);
    }


    public function challenge(Request $request): JsonResponse
    {
        $content = $request->get('content');

        $commonReturn = [
            'challenge' => $content['challenge']
        ];
        return $this->json($commonReturn);
    }


    /**
     * 支付完成通知
     *
     * @param Request $request
     * @return JsonResponse
     * @throws OrderException
     */
    public function paymentNotify(Request $request): JsonResponse
    {
        $requestAll = $request->all();
        $msgData    = $requestAll['msg'];

        $data        = json_decode($msgData, 1);
        $cpExtra     = $data['cp_extra'];
        $cpExtraData = json_decode($cpExtra, 1);

        $orderPay = new OrderPay(1, $cpExtraData['shopId'], $data['out_order_no']);
        $orderPay->setPayData([
            'payMethod' => CodeEnum::ORDER_PAY_CHANNEL_MONEY,
            'payEvent'  => CodeEnum::ORDER_PAY_EVENT_ORDER
        ]);

        // 判断是否有用户信息
        $orderInfo = $orderPay->getOrderInfo();
        $userInfo  = CustomerPlatformModel::getUserInfoByColumn([
            'userId'     => $orderInfo->userId,
            'platformId' => PlatformCodeEnum::PLATFORM_APPLET_DOUYIN
        ], ['openId', 'unionid']);

        // 设置支付用户信息配置
        $orderPay->setUserInfo([
            'userId'     => $orderInfo->userId,
            'openId'     => $userInfo->openId ?? '',
            'platformId' => PlatformCodeEnum::PLATFORM_APPLET_DOUYIN,
        ]);

        $orderPay->cashPay();
        $orderPay->successV2();
        $orderPay->finish();
        return $this->success();
    }

    /**
     * 核销通知
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function couponVerifyNotify(Request $request): JsonResponse
    {
        $requestAll = $request->all();
        $msgData    = $requestAll['msg'];

        $data    = json_decode($msgData, 1);
        $cpExtra = $data['cp_extra'];

        $cpExtraData = json_decode($cpExtra, 1);

        $dyOrder = new OrderDyService(1, $cpExtraData['shopId']);

        $dyOrder->updateDyOrderCoupon($data);

        return $this->success();
    }

    public function success(array $data = null): JsonResponse
    {
        $commonReturn = [
            'err_no'   => 0,
            'err_tips' => 'success',
            'data'     => $data
        ];
        return $this->json($commonReturn);
    }


    public function fail(int $code, string $msg = '', array $data = null): JsonResponse
    {
        $commonReturn = [
            'err_no'   => $code,
            'err_tips' => $msg,
            'data'     => $data
        ];
        return $this->json($commonReturn);
    }
}
